# -*- coding: utf-8 -*-
# @Time : 2021/9/4 9:29
# @Author : 唐宁
# @Site : 数据库连接核心封装类
# @File : MysqlDb.py
# @Software: PyCharm
import pymysql


def cal_page(page_number, page_size):
    """
    计算mysql 分页
    :param page_number: 页码
    :param page_size: 大小
    :return: page_number,page_size
    """
    if page_number == 1 or page_number == 0:
        return 0, page_size
    else:
        return (page_number - 1) * page_size, page_size


class MysqlDb:

    def __init__(self, host, port, user, passwd, db):
        """
        数据库连接基本配置信息
        :param host: 数据库地址
        :param port: 端口
        :param user: 账号
        :param passwd: 密码
        :param db: 库名
        """
        self.conn = pymysql.connect(
            host=host,
            port=port,
            user=user,
            passwd=passwd,
            db=db
        )
        # 通过 cursor() 创建游标对象，并让查询结果以字典格式输出
        self.cur = self.conn.cursor(cursor=pymysql.cursors.DictCursor)

    # 对象资源被释放时触发，在对象即将被删除时的最后操作
    def __del__(self):
        # 关闭游标
        self.cur.close()
        # 关闭数据库连接
        self.conn.close()

    def select_list(self, sql, vo):
        """
        查询方法
        :param vo: 解析对象
        :param sql: 执行的查询语句
        :return: list
        """
        # 使用 execute() 执行sql
        self.cur.execute(sql)
        # 使用 fetchall() 获取查询结果
        return [vo(**result) for result in self.cur.fetchall()]

    def select_one(self, sql, vo):
        """
        查询方法
        :param vo: 解析对象
        :param sql: 执行的查询语句
        :return: 单体
        """
        # 使用 execute() 执行sql
        self.cur.execute(sql)
        # 使用 fetchall() 获取查询结果
        return vo(**self.cur.fetchone())

    def select_page(self, sql, page_number, page_size, vo):
        """
        分页查询封装
        :param sql: 执行的sql语句
        :param page_number: 页码
        :param page_size: 大小
        :param vo: 实体
        :return: total,rows
        """
        # 查询sql总条数，拼接select count(*) from
        count_sql = f"select count(*) as 'num' from ( {sql} ) a "
        print("查询总数sql: ", count_sql)
        # 执行总查询
        self.cur.execute(count_sql)
        total = self.cur.fetchone()['num']
        # 执行核心sql
        # 计算页码
        cal_page_number, page_size = cal_page(page_number, page_size)
        # 拼接limit
        core_sql = f"{sql} LIMIT {cal_page_number},{page_size} "
        print("核心sql: ", core_sql)
        self.cur.execute(core_sql)
        # 组装数据
        return total, [vo(**result) for result in self.cur.fetchall()]

    def execute_db(self, sql):
        """更新/插入/删除"""
        try:
            # 使用 execute() 执行sql
            self.cur.execute(sql)
            # 提交事务
            self.conn.commit()
            # 返回行数
            return self.cur.rowcount
        except Exception as e:
            print("操作出现错误：{}".format(e))
            # 回滚所有更改
            self.conn.rollback()
            return 0
